Skip to main content

Runcontrol Setup for Application Exe

Description

This document describes how to configure a stream that runs a Windows executable in a RunControl batch.

Note: these steps apply to RunControl 5.3.x only. From 5.5.4 onwards do not do any of this — configure the executable from the App Batch option on the Stream Definition screen instead.

On 5.3.x there is no Stream Definition screen in the application, so a stream is created by writing two rows directly into the RunControl database — one in STREAMDEF holding the stream definition, and one in BATCHSTREAM mapping that stream to a batch and holding its dependencies.


Step 1 — Pick the ExecutorId from ExecutorDef

-- SQL Server
SELECT ExecutorId, ExecutorUrl
FROM ExecutorDef;
-- Oracle
SELECT "ExecutorId", "ExecutorUrl"
FROM "ExecutorDef";

How to choose: pick the executor id for the same Windows server URL where the .exe is deployed.


Step 2 — Identify the batch and pick the BATCHID from BATCHDEF

  1. In the DH application, identify the batch name. Note the batch name exactly as displayed.
  2. Look that name up in BATCHDEF:
-- SQL Server
SELECT BATCHID, BATCHNAME
FROM BATCHDEF
WHERE BATCHNAME = 'your batch name';
-- Oracle
SELECT "BATCHID", "BATCHNAME"
FROM "BATCHDEF"
WHERE "BATCHNAME" = 'your batch name';

Step 3 — Decide the new STREAMID

3.1 Check the stream IDs present for that batch

-- SQL Server  (example: BATCHID = 4)
SELECT bs.BATCHID, bs.STREAMID, sd.STREAMNAME
FROM BATCHSTREAM bs
JOIN STREAMDEF sd ON sd.STREAMID = bs.STREAMID
WHERE bs.BATCHID = 4
ORDER BY bs.STREAMID;
-- Oracle
SELECT bs."BATCHID", bs."STREAMID", sd."STREAMNAME"
FROM "BATCHSTREAM" bs
JOIN "STREAMDEF" sd ON sd."STREAMID" = bs."STREAMID"
WHERE bs."BATCHID" = 4
ORDER BY bs."STREAMID";

3.2 Pick the new STREAMID

Keep the batch number as the prefix. A stream's ID should begin with the BATCHID it belongs to, so the ID itself tells you which batch it is in. For BATCHID = 4 the stream IDs look like 4001, 4006, 4014.

Then pick the number according to where we want the stream to sit:

What you wantWhat to useExample — BATCHID 4, existing streams 4001, 4006, 4014
The new stream at the end of the batchMAX(STREAMID) + 4 for that batch4014 + 4 = 4018
The new stream between two existing streamsany free number between the twobetween 4006 and 40144010

Step 4 — Build the stream definition JSON

This is the JSON that goes into STREAMDEF.STREAMDESC.

4.1 Structure

STREAMDESC
└── streamName, streamId
└── flows[]
├── flowId, name, executorID, flowDependencies[]
└── process[]
├── processId, processName
├── processBinary
├── processArguments[]
├── processDependencies[]
├── processType
├── infoLog, errorLog, processReport

4.2 Field reference

Root

FieldDescription
streamNameStream name. Max 25 chars, must match STREAMDEF.STREAMNAME
streamIdThe STREAMID from Step 3, quoted — "4018"
flowsArray — normally one flow

flows[]

FieldDescription
flowId"1"
nameName of the flow
executorIDExecutorId from Step 1, quoted — "1"
flowDependencies[] for a single-flow stream
processArray — one entry per program

process[]

FieldDescription
processId"1", "2", … numbering starts at 1
processNameUnique, readable name
processBinaryFull path to the .exe
processArgumentsArguments — one array element per token
processDependenciesprocessIds that must finish first; [] = starts immediately
processType"OTHER" for a customer exe
infoLogFull path of the normal log file
errorLogFull path of the error log file
processReport"" for a customer exe

⚠️ Backslashes: in JSON a single \ does not work — always double it. Z:\DH\App.exe must be written as "Z:\\DH\\App.exe". This applies to every path — processBinary, infoLog, errorLog, processReport, and any path inside processArguments.

4.3 Example — one Windows exe in a stream

{
"streamName": "GL Recon Utility",
"streamId": "4018",
"flows": [
{
"flowId": "1",
"name": "gl_recon_flow",
"flowDependencies": [],
"executorID": "1",
"process": [
{
"processId": "1",
"processName": "gl_recon_util",
"processBinary": "Z:\\DEMO\\DH\\SH_PROGRAMS\\GLReconUtility.exe",
"processArguments": [
"-mode",
"EOD",
"-input",
"Z:\\DEMO\\DH\\SH_DATA\\B_4\\gl_input.txt",
"-output",
"Z:\\DEMO\\DH\\SH_DATA\\B_4\\gl_output.txt"
],
"processDependencies": [],
"processReport": "",
"processType": "OTHER",
"infoLog": "Z:\\DEMO\\DH\\SH_LOGS\\B_4\\log_gl_recon_util.txt",
"errorLog": "Z:\\DEMO\\DH\\SH_LOGS\\B_4\\diag_log_gl_recon_util.txt"
}
]
}
]
}

4.4 Example — two exes, second waits for the first

Only the process array changes:

"process": [
{
"processId": "1",
"processName": "gl_extract",
"processBinary": "Z:\\DEMO\\DH\\SH_PROGRAMS\\GLExtract.exe",
"processArguments": ["-date", "EOD"],
"processDependencies": [],
"processReport": "",
"processType": "OTHER",
"infoLog": "Z:\\DEMO\\DH\\SH_LOGS\\B_4\\log_gl_extract.txt",
"errorLog": "Z:\\DEMO\\DH\\SH_LOGS\\B_4\\diag_log_gl_extract.txt"
},
{
"processId": "2",
"processName": "gl_recon_util",
"processBinary": "Z:\\DEMO\\DH\\SH_PROGRAMS\\GLReconUtility.exe",
"processArguments": ["-mode", "EOD"],
"processDependencies": ["1"],
"processReport": "",
"processType": "OTHER",
"infoLog": "Z:\\DEMO\\DH\\SH_LOGS\\B_4\\log_gl_recon_util.txt",
"errorLog": "Z:\\DEMO\\DH\\SH_LOGS\\B_4\\diag_log_gl_recon_util.txt"
}
]

4.5 Validate the JSON before it goes near the database

  1. Paste it into a JSON validator (VS Code, Notepad++ JSON plugin, any validator).
  2. Confirm: no trailing commas, every string quoted, every backslash doubled.
  3. Confirm streamId inside the JSON is the same number you will insert into STREAMDEF.STREAMID.

Step 5 — Build the dependency JSON

This is the JSON that goes into BATCHSTREAM.STREAMDEP. It lists the streams that must finish before this one starts.

{ "dependencies": [] }
{ "dependencies": [110, 120] }
  • Empty list → the stream can start as soon as the batch starts.
  • The IDs are StreamIds (numbers, not quoted), and they must belong to the same batch.
  • Do not create a loop (A waits for B and B waits for A) — the batch will never start.

Step 6 — Insert the rows

Both JSON documents are now ready — STREAMDESC from Step 4 and STREAMDEP from Step 5. Insert into STREAMDEF first, then BATCHSTREAM.

Note: always name the columns. STREAMDEF's column order is STREAMID, STREAMDESC, STREAMNAME — the binary column is second and the name third, which is the opposite of what most people assume.

6.1 SQL Server

BEGIN TRANSACTION;

DECLARE @StreamId INT = 4018; -- from Step 3
DECLARE @BatchId INT = 4; -- from Step 2
DECLARE @StreamName VARCHAR(25) = 'GL Recon Utility';

-- NOTE: VARCHAR, not NVARCHAR — NVARCHAR stores the text as UTF-16, which DH cannot read
DECLARE @StreamDesc VARCHAR(MAX) = '<<paste the validated JSON from Step 4 here>>';
DECLARE @StreamDep VARCHAR(MAX) = '{ "dependencies": [] }'; -- from Step 5

-- 1) the stream definition
INSERT INTO STREAMDEF (STREAMID, STREAMNAME, STREAMDESC)
VALUES (@StreamId, @StreamName, CONVERT(VARBINARY(MAX), @StreamDesc));

-- 2) map the stream to the batch
INSERT INTO BATCHSTREAM (BATCHID, STREAMID, STREAMDEP, IsActive)
VALUES (@BatchId, @StreamId, CONVERT(VARBINARY(MAX), @StreamDep), 'Y');

-- verify before committing
SELECT sd.STREAMID, sd.STREAMNAME, bs.BATCHID, bs.IsActive,
CONVERT(VARCHAR(MAX), bs.STREAMDEP) AS StreamDepText,
CONVERT(VARCHAR(MAX), sd.STREAMDESC) AS StreamDescText
FROM STREAMDEF sd
JOIN BATCHSTREAM bs ON bs.STREAMID = sd.STREAMID
WHERE sd.STREAMID = @StreamId;

-- COMMIT; -- uncomment only after the SELECT above looks correct

Note: the JSON can also be inlined directly, without the variable — CONVERT(VARBINARY(MAX), '<json>'). If you do, use a plain literal and not N'...', and double every single quote inside the JSON.

6.2 Oracle

STREAMDESC is a BLOB NOT NULL, and the JSON is normally longer than a single SQL literal allows, so it is built up in a PL/SQL block. Paste the JSON in pieces — each APPEND literal under 4000 characters, as many lines as you need. Split it anywhere; the pieces are simply joined end to end.

DECLARE
v_StreamId NUMBER := 4018; -- from Step 3
v_BatchId NUMBER := 4; -- from Step 2
v_StreamName VARCHAR2(25) := 'GL Recon Utility';

v_DescClob CLOB;
v_DepClob CLOB;
v_DescBlob BLOB;
v_DepBlob BLOB;

v_dest_offset INTEGER := 1;
v_src_offset INTEGER := 1;
v_lang_context INTEGER := DBMS_LOB.DEFAULT_LANG_CTX;
v_warning INTEGER;
BEGIN
-- 1) the STREAMDESC JSON from Step 4, in chunks of under 4000 characters
DBMS_LOB.CREATETEMPORARY(v_DescClob, TRUE);
DBMS_LOB.APPEND(v_DescClob, TO_CLOB('<<paste chunk 1 of the JSON here>>'));
DBMS_LOB.APPEND(v_DescClob, TO_CLOB('<<paste chunk 2 of the JSON here>>'));
-- ... add as many APPEND lines as the JSON needs

-- 2) the STREAMDEP JSON from Step 5
v_DepClob := TO_CLOB('{ "dependencies": [] }');

-- 3) CLOB -> BLOB
DBMS_LOB.CREATETEMPORARY(v_DescBlob, TRUE);
DBMS_LOB.CONVERTTOBLOB(v_DescBlob, v_DescClob, DBMS_LOB.LOBMAXSIZE,
v_dest_offset, v_src_offset,
DBMS_LOB.DEFAULT_CSID, v_lang_context, v_warning);

v_dest_offset := 1;
v_src_offset := 1;
v_lang_context := DBMS_LOB.DEFAULT_LANG_CTX;

DBMS_LOB.CREATETEMPORARY(v_DepBlob, TRUE);
DBMS_LOB.CONVERTTOBLOB(v_DepBlob, v_DepClob, DBMS_LOB.LOBMAXSIZE,
v_dest_offset, v_src_offset,
DBMS_LOB.DEFAULT_CSID, v_lang_context, v_warning);

-- 4) the stream definition
INSERT INTO "STREAMDEF" ("STREAMID", "STREAMNAME", "STREAMDESC")
VALUES (v_StreamId, v_StreamName, v_DescBlob);

-- 5) map the stream to the batch (note: ISACTIVE is upper case on this table)
INSERT INTO "BATCHSTREAM" ("BATCHID", "STREAMID", "STREAMDEP", "ISACTIVE")
VALUES (v_BatchId, v_StreamId, v_DepBlob, 'Y');
END;
/

-- verify before committing
SELECT sd."STREAMID", sd."STREAMNAME", bs."BATCHID", bs."ISACTIVE",
UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(bs."STREAMDEP", 2000, 1)) AS "StreamDepText",
UTL_RAW.CAST_TO_VARCHAR2(DBMS_LOB.SUBSTR(sd."STREAMDESC", 2000, 1)) AS "StreamDescHead"
FROM "STREAMDEF" sd
JOIN "BATCHSTREAM" bs ON bs."STREAMID" = sd."STREAMID"
WHERE sd."STREAMID" = 4018;

-- COMMIT; -- run only after the SELECT above looks correct

Note:

  • Oracle opens a transaction on its own — there is no BEGIN TRANSACTION. Nothing is permanent until you COMMIT, and ROLLBACK; undoes the whole block.
  • DBMS_LOB.SUBSTR returns the first 2000 bytes only, so StreamDescHead shows the start of the JSON. That is enough to confirm it is readable and that the backslashes survived.
  • STREAMDEP is only a few dozen bytes, so the BATCHSTREAM insert can be run on its own as a plain statement instead — UTL_RAW.CAST_TO_RAW('{ "dependencies": [] }'). Do not use UTL_RAW.CAST_TO_RAW for STREAMDESC: a RAW value is limited to 2000 bytes in SQL and a string literal to 4000, and a stream definition normally exceeds both.

Common failures and what they usually mean

SymptomMost likely cause
Stream does not appear in the batch at allBATCHSTREAM.IsActive (Oracle: ISACTIVE) is not 'Y', or the row was inserted against the wrong BATCHID
Stream appears but never startsIt is waiting on a STREAMDEP entry that never completes — or a circular dependency
Stream fails instantly, no log fileBad processBinary path (usually a single backslash), exe not on that executor, or the log folder does not exist
Oracle rejects the insert with a check-constraint errorSome environments carry an IS JSON check on BATCHSTREAM.STREAMDEP — your STREAMDEP is not valid JSON
Oracle rejects the insert with a foreign-key errorThe STREAMDEF row was not inserted first, or the BATCHID does not exist
Oracle raises ORA-01704 or ORA-06502 on insertThe JSON was inlined as a literal instead of built as a CLOB — use the PL/SQL block in Step 6.2
STREAMDESC reads back as ????? or unreadableStored as UTF-16 — on SQL Server, declare the variable as VARCHAR(MAX) and not NVARCHAR(MAX)

Rollback

Delete in the reverse order of insertion, inside a transaction:

SQL Server

BEGIN TRANSACTION;

DELETE FROM BATCHSTREAM WHERE STREAMID = <your streamid>;
DELETE FROM STREAMDEF WHERE STREAMID = <your streamid>;

-- COMMIT;

Oracle

DELETE FROM "BATCHSTREAM" WHERE "STREAMID" = <your streamid>;
DELETE FROM "STREAMDEF" WHERE "STREAMID" = <your streamid>;

-- COMMIT; -- or ROLLBACK; to undo

Note: if the batch has already run with this stream, do not delete — set BATCHSTREAM.IsActive = 'N' (Oracle: ISACTIVE) instead, so the run history stays intact.